home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / ply15dat.zip / RINGS.C < prev    next >
C/C++ Source or Header  |  1992-09-19  |  7KB  |  200 lines

  1. /*
  2.  * rings.c - Create objects with 6 pentagonal rings which connect the midpoints
  3.  *     of the edges of a dodecahedron.  A pyramid of these objects is formed,
  4.  *     which the viewer looks upon from the point.  A plane is placed behind
  5.  *     the pyramid for shadows.  No object is clipped.  Three light sources.
  6.  *
  7.  * Version:  2.2 (11/17/87)
  8.  * Author:  Eric Haines, 3D/Eye, Inc.
  9.  *
  10.  * SIZE_FACTOR determines the number of objects output.
  11.  *     Each object has 30 cylinders and 30 spheres.
  12.  *     Total objects = SF*SF + (SF-1)*(SF-1) + ... + 1 plus 1 backdrop square.
  13.  *     formula for # of spheres or cylinders = 5*SF*(SF+1)*(2*SF+1)
  14.  *
  15.  *     SIZE_FACTOR      # spheres       # cylinders     # squares
  16.  *          1               30                30             1
  17.  *          2              150               150             1
  18.  *          3              420               420             1
  19.  *
  20.  *          7             4200              4200             1
  21.  */
  22.  
  23. #include <stdio.h>
  24. #include <math.h>
  25. #ifdef MAC
  26. #include <console.h>
  27. #endif
  28.  
  29. #include "def.h"
  30. #include "lib.h"
  31.  
  32. #define SIZE_FACTOR   2
  33.  
  34. /* if spread out is > 1, succeeding layers spread out more */
  35. #define SPREAD_OUT              1
  36.  
  37. /* Create the set of 30 points needed to generate the rings */
  38. static void
  39. create_dodec(double minor_radius, COORD4 vertex[30])
  40. {
  41.     long    num_vertex, num_pentagon ;
  42.     COORD4  temp_vertex ;
  43.     MATRIX  x_matrix, z_matrix ;
  44.     double  scale, x_rotation, z_rotation ;
  45.  
  46.  
  47.     /* scale object to fit in a sphere of radius 1 */
  48.  
  49.     scale = 1.0 / ( 1.0 + minor_radius ) ;
  50.     /*
  51.      * define one pentagon as on the XY plane, with points starting along +X
  52.      * and N fifths of the way around the Z axis.
  53.      */
  54.     for ( num_vertex = 0 ; num_vertex < 5 ; ++num_vertex ) {
  55.         vertex[num_vertex].x = scale * cos( (double)num_vertex * 2.0*PI/5.0 ) ;
  56.         vertex[num_vertex].y = scale * sin( (double)num_vertex * 2.0*PI/5.0 ) ;
  57.         vertex[num_vertex].z = 0.0 ;
  58.         vertex[num_vertex].w = 1.0 ;
  59.     }
  60.  
  61.     /*
  62.      * find the rotation angle (in radians) along the X axis:
  63.      * angle between two adjacent dodecahedron faces.
  64.      */
  65.     x_rotation = 2.0 *
  66.                 acos( cos( (double)(PI/3.0) ) / sin( (double)(PI/5.0) ) ) ;
  67.     lib_create_rotate_matrix( x_matrix, X_AXIS, x_rotation ) ;
  68.  
  69.     /*
  70.      * Find each of the other 5 pentagons:  rotate along the X axis,
  71.      * then rotate on the Z axis.
  72.      */
  73.     for ( num_pentagon = 1 ; num_pentagon < 6 ; ++num_pentagon ) {
  74.         /*
  75.          * find the rotation angle (in radians) along the Z axis:
  76.          * 1/10th plus N fifths of the way around * 2 * PI.
  77.          */
  78.         z_rotation = PI*( 2.0*(double)(num_pentagon-1)+1.0 ) / 5.0 ;
  79.         lib_create_rotate_matrix( z_matrix, Z_AXIS, z_rotation ) ;
  80.  
  81.         for ( num_vertex = 0 ; num_vertex < 5 ; ++num_vertex ) {
  82.  
  83.             lib_transform_coord( &temp_vertex
  84.                                , &vertex[num_vertex]
  85.                                , x_matrix
  86.                                ) ;
  87.  
  88.             lib_transform_coord( &vertex[5*num_pentagon+num_vertex]
  89.                                , &temp_vertex
  90.                                , z_matrix
  91.                                ) ;
  92.         }
  93.     }
  94. }
  95.  
  96. void
  97. main(int argc, char *argv[])
  98. {
  99.     COORD4  base_pt, apex_pt, offset ;
  100.     COORD4  wall[4], dodec[30] ;
  101.     COORD4  from, at, up, dir;
  102.     COORD4  wvec, light ;
  103.     COORD4  back_color, ring_color[6] ;
  104.     long    prev_elem ;
  105.     long    num_elem ;
  106.     long    num_depth, num_objx, num_objz ;
  107.     double  radius ;
  108.     double  spread, y_diff, xz_diff ;
  109.     char *c[6];
  110.     int cind = 0;
  111.  
  112.    /* We are using Polyray */
  113.    lib_set_raytracer(OUTPUT_POLYRAY);
  114.  
  115.     radius = 0.07412 ;  /* cone and sphere radius */
  116.  
  117.     /* calculate spread of objects */
  118.     spread = 1 / sin( (double)( PI/8.0 ) ) ;
  119.     if ( SPREAD_OUT <= spread ) {
  120.         y_diff = spread / SPREAD_OUT ;
  121.         xz_diff = 1.0 ;
  122.     }
  123.     else {
  124.         y_diff = 1.0 ;
  125.         xz_diff = SPREAD_OUT / spread ;
  126.     }
  127.  
  128.     /* output viewpoint */
  129.     SET_COORD( from, -1.0, -spread, 0.5 ) ;
  130.     SET_COORD( at, from.x, from.y + 1.0, from.z ) ;
  131.     SET_COORD( up, 0.0, 0.0, 1.0 ) ;
  132.     lib_output_viewpoint( &from, &at, &up, 45.0, 1.0, 1.0, 256, 256);
  133.  
  134.     /* output background color - UNC sky blue */
  135.     /* note that the background color should never be seen */
  136.     SET_COORD( back_color, 0.078, 0.361, 0.753 ) ;
  137.     lib_output_background_color( &back_color ) ;
  138.  
  139.     /* output light source */
  140.     SET_COORD4( light, 3.0, -spread, 3.0, 0.6 ) ;
  141.     lib_output_light( &light ) ;
  142.     SET_COORD4( light, -4.0, -spread, 1.0, 0.6 ) ;
  143.     lib_output_light( &light ) ;
  144.     SET_COORD4( light, 2.0, -spread, -4.0, 0.6 ) ;
  145.     lib_output_light( &light ) ;
  146.  
  147.     /* output wall polygon - white */
  148.     SET_COORD( back_color, 1.0, 1.0, 1.0 ) ;
  149.     lib_output_color(&back_color, 0.2, 0.7, 0.0, 0.0, 0.0, 0.0, 0.0);
  150.     /* just spans 45 degree view + 1% */
  151.     wvec.y = y_diff * ( SIZE_FACTOR + 1 ) ;
  152.     wvec.x = wvec.z = 1.01 * ( wvec.y - from.y ) * tan( PI / 8.0 ) ;
  153.     SET_COORD( wall[0],  wvec.x+from.x, wvec.y,  wvec.z+from.z ) ;
  154.     SET_COORD( wall[1], -wvec.x+from.x, wvec.y,  wvec.z+from.z ) ;
  155.     SET_COORD( wall[2], -wvec.x+from.x, wvec.y, -wvec.z+from.z ) ;
  156.     SET_COORD( wall[3],  wvec.x+from.x, wvec.y, -wvec.z+from.z ) ;
  157.     lib_output_polygon(4, wall);
  158.  
  159.     /* set up ring colors - RGB and complements */
  160.     SET_COORD(ring_color[0], 1.0, 0.0, 0.0);
  161.     SET_COORD(ring_color[1], 0.0, 1.0, 0.0);
  162.     SET_COORD(ring_color[2], 0.0, 0.0, 1.0);
  163.     SET_COORD(ring_color[3], 0.0, 1.0, 1.0);
  164.     SET_COORD(ring_color[4], 1.0, 0.0, 1.0);
  165.     SET_COORD(ring_color[5], 1.0, 1.0, 0.0);
  166.  
  167.     create_dodec( radius, dodec ) ;
  168.     /* radius of osculating cylinders and spheres (no derivation given) */
  169.     base_pt.w = apex_pt.w = radius ;
  170.  
  171.     for ( num_depth = 0 ; num_depth < SIZE_FACTOR ; ++num_depth ) {
  172.         offset.y = y_diff * (double)(num_depth+1) ;
  173.         for ( num_objz = 0 ; num_objz <= num_depth ; ++num_objz ) {
  174.             offset.z = xz_diff * (double)(2*num_objz - num_depth) ;
  175.             for ( num_objx = 0 ; num_objx <= num_depth ; ++num_objx ) {
  176.                 offset.x = xz_diff * (double)(2*num_objx - num_depth) ;
  177.                 for ( num_elem = 0 ; num_elem < 30 ; ++num_elem ) {
  178.                     COPY_COORD( base_pt, dodec[num_elem] ) ;
  179.                     ADD2_COORD( base_pt, offset ) ;
  180.                     if ( num_elem%5 == 0 ) {
  181.                         prev_elem = num_elem + 4 ;
  182.                         /* new ring beginning - output color */
  183.                 lib_output_color(&ring_color[cind], 0.2, 0.5, 0.0,
  184.                      0.5, 10.0, 0.0, 0.0);
  185.                         cind = num_elem/5;
  186.                        }
  187.                     else {
  188.                         prev_elem = num_elem - 1 ;
  189.                        }
  190.                     COPY_COORD( apex_pt, dodec[prev_elem] ) ;
  191.                     ADD2_COORD( apex_pt, offset ) ;
  192.  
  193.                     lib_output_cylcone( &base_pt, &apex_pt, OUTPUT_CURVES);
  194.                     lib_output_sphere( &base_pt, OUTPUT_CURVES);
  195.                 }
  196.             }
  197.         }
  198.     }
  199. }
  200.